package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.DeviceFaultMap;
import com.ruoyi.system.domain.DisplayTest;
import com.ruoyi.system.domain.bo.DisplayTestBo;
import com.ruoyi.system.domain.vo.DeviceFaultMapVo;
import com.ruoyi.system.domain.vo.DisplayTestVo;
import com.ruoyi.system.mapper.DeviceFaultMapMapper;
import com.ruoyi.system.mapper.DisplayTestMapper;
import com.ruoyi.system.service.IDisplayTestService;
import com.ruoyi.system.service.ISysDictDataService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import oshi.SystemInfo;
import oshi.hardware.Display;
import oshi.hardware.HardwareAbstractionLayer;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 显示器检测Service业务层处理
 *
 * @author Panda
 * @date 2023-11-27
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class DisplayTestServiceImpl implements IDisplayTestService {

    private final DisplayTestMapper baseMapper;

    private final DeviceFaultMapMapper deviceFaultMapMapper;

    private final ISysDictDataService iSysDictDataService;

    @Override
    public R getDisplays(String poId, String remark) {
        // 初始化系统信息对象
        SystemInfo systemInfo = new SystemInfo();
        //获取品牌映射字典
        SysDictData sysDictData = new SysDictData();
        sysDictData.setDictType("test_display_brand_map");
        List<SysDictData> dictDatas = iSysDictDataService.selectDictDataList(sysDictData);
        Map<String, String> brandMap;
        if (CollectionUtils.isNotEmpty(dictDatas)) {
            brandMap = dictDatas.stream().filter(d -> d.getStatus().equals("0")).collect(Collectors.toMap(SysDictData::getDictLabel, SysDictData::getDictValue));
        } else {
            brandMap = null;
        }

// 获取硬件信息
        HardwareAbstractionLayer hardware = systemInfo.getHardware();

        List<Display> displays = hardware.getDisplays();
        List<DisplayTest> displayTests = displays.stream().map(display -> {
            log.info(display.toString());
            String originBrand = display.toString().substring(display.toString().indexOf("Manuf. ID=") + 10, display.toString().indexOf(", Product ID=")).trim();
            String size = null;
            try {
                String sizeStr = display.toString().substring(display.toString().indexOf("EDID") + 9, display.toString().indexOf("Preferred Timing:")).trim();
                String widthAndHigh = sizeStr.substring(0, sizeStr.indexOf("cm")).trim();
                String[] split = widthAndHigh.split("x");
                double width = Double.parseDouble(split[0]);
                double high = Double.parseDouble(split[1]);
                double inch = Math.sqrt(width * width + high * high) / 2.54;
                size = String.format("%.1f", inch);

            } catch (Exception e) {
                log.info("无法获取到尺寸");
            }
            String model = null;
            try {
                if (display.toString().contains("Monitor Name:")) {
                    model = display.toString().substring(display.toString().indexOf("Monitor Name:"));
                    String[] models = model.split("\n");
                    model = models[0];
                    models = model.split(":");
                    model = models[1].trim();

                }

            } catch (Exception e) {
                log.info("无法获取到型号");
            }
            String sn = null;
            try {
                if (display.toString().contains("Serial Number:")) {

                    sn = display.toString().substring(display.toString().indexOf("Serial Number:"));
                    String[] sns = sn.split("\n");
                    sn = sns[0];
                    sns = sn.split(":");
                    sn = sns[1].trim();
                }
            } catch (Exception e) {
                log.info("无法获取到SN");
            }
            String resolution = null;
            try {
                if (display.toString().contains("Active Pixels")) {

                    resolution = display.toString().substring(display.toString().indexOf("Active Pixels"));
                    String[] resolutions = resolution.split("\n");
                    resolution = resolutions[0];
                    resolutions = resolution.split("\\s+");
                    resolution = resolutions[2].trim();
                }
            } catch (Exception e) {
                log.info("无法获取到分辨率");
            }

            DisplayTest displayTest = new DisplayTest();
            displayTest.setId(UUID.fastUUID().toString());
            String brand = originBrand;
            if (brandMap != null) {
                brand = brandMap.get(originBrand);
            }
            if (StringUtils.isBlank(brand)) {
                brand = originBrand;
            }
            displayTest.setBrand(brand);
            displayTest.setOriginBrand(originBrand);
            displayTest.setModel(model);
            displayTest.setSn(sn);
            displayTest.setResolution(resolution);
            displayTest.setSize(size);
            displayTest.setPoId(poId);
            displayTest.setRemark(remark);
            return displayTest;
        }).collect(Collectors.toList());
        //去除没有读不到sn的设备
        List<DisplayTest> collect = displayTests.stream().filter(d -> StringUtils.isNotBlank(d.getSn())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(collect)) {
            Set<String> sns = collect.stream().map(DisplayTest::getSn).collect(Collectors.toSet());
            //判断设备是不是已经读取过了
            LambdaQueryWrapper<DisplayTest> displayTestLambdaQueryWrapper = Wrappers.lambdaQuery(DisplayTest.class);
            displayTestLambdaQueryWrapper.in(DisplayTest::getSn, sns);
            List<DisplayTestVo> displayTestVos = baseMapper.selectVoList(displayTestLambdaQueryWrapper);
            if (CollectionUtils.isNotEmpty(displayTestVos)) {
                DisplayTestVo displayTestVo = displayTestVos.get(0);
                //查询关联的故障
                LambdaQueryWrapper<DeviceFaultMap> deviceFaultMapLambdaQueryWrapper = Wrappers.lambdaQuery(DeviceFaultMap.class);
                deviceFaultMapLambdaQueryWrapper.eq(DeviceFaultMap::getDeviceId, displayTestVo.getId());
                List<DeviceFaultMap> deviceFaultMapVos = deviceFaultMapMapper.selectList(deviceFaultMapLambdaQueryWrapper);
                List<String> faults = deviceFaultMapVos.stream().map(DeviceFaultMap::getFaultName).collect(Collectors.toList());
                displayTestVo.setDeviceFaultMaps(faults);
                return R.ok("请勿重复读取,或者SN不正确并检查PO号是否正确", displayTestVo);
            }
            //判断有没有设置实际品牌
            String msg;
            if (collect.get(0).getBrand().equals(collect.get(0).getOriginBrand())) {
                msg = "请修正实际品牌并点击确认";
            } else {
                msg = "读取成功";

                baseMapper.insertBatch(collect);
            }
            DisplayTest displayTest = collect.get(0);
            DisplayTestVo displayTestVo = BeanUtil.toBean(displayTest, DisplayTestVo.class);

            LambdaQueryWrapper<DeviceFaultMap> deviceFaultMapLambdaQueryWrapper = Wrappers.lambdaQuery(DeviceFaultMap.class);
            deviceFaultMapLambdaQueryWrapper.eq(DeviceFaultMap::getDeviceId, displayTestVo.getId());
            List<DeviceFaultMap> deviceFaultMapVos = deviceFaultMapMapper.selectList(deviceFaultMapLambdaQueryWrapper);
            List<String> faults = deviceFaultMapVos.stream().map(DeviceFaultMap::getFaultName).collect(Collectors.toList());
            displayTestVo.setDeviceFaultMaps(faults);
            return R.ok(msg, displayTestVo);

        } else {
            return R.fail("未知错误");
        }
    }

    /**
     * 查询显示器检测
     */
    @Override
    public DisplayTestVo queryById(String id) {
        LambdaQueryWrapper<DeviceFaultMap> deviceFaultMapLambdaQueryWrapper = Wrappers.lambdaQuery(DeviceFaultMap.class);
        deviceFaultMapLambdaQueryWrapper.eq(DeviceFaultMap::getDeviceId, id);
        List<DeviceFaultMap> deviceFaultMapVos = deviceFaultMapMapper.selectList(deviceFaultMapLambdaQueryWrapper);
        List<String> faults = deviceFaultMapVos.stream().map(DeviceFaultMap::getFaultName).collect(Collectors.toList());

        DisplayTestVo displayTestVo = baseMapper.selectVoById(id);
        displayTestVo.setDeviceFaultMaps(faults);
        return displayTestVo;
    }

    /**
     * 查询显示器检测列表
     */
    @Override
    public TableDataInfo<DisplayTestVo> queryPageList(DisplayTestBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<DisplayTest> lqw = buildQueryWrapper(bo);
        Page<DisplayTestVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<DisplayTestVo> displayTestVos = result.getRecords();
        Set<String> deviceIds = displayTestVos.stream().map(DisplayTestVo::getId).collect(Collectors.toSet());

        LambdaQueryWrapper<DeviceFaultMap> deviceFaultMapLambdaQueryWrapper = Wrappers.lambdaQuery(DeviceFaultMap.class);
        deviceFaultMapLambdaQueryWrapper.in(DeviceFaultMap::getDeviceId, deviceIds);
        List<DeviceFaultMap> deviceFaultMapVos = deviceFaultMapMapper.selectList(deviceFaultMapLambdaQueryWrapper);
        Map<String, List<String>> stringListMap = deviceFaultMapVos.stream().collect(Collectors.groupingBy(DeviceFaultMap::getDeviceId, Collectors.mapping(DeviceFaultMap::getFaultName, Collectors.toList())));
        if (CollectionUtils.isNotEmpty(stringListMap)) {
            displayTestVos.forEach(d -> {
                d.setDeviceFaultMaps(stringListMap.get(d.getId()));
            });
        }

        return TableDataInfo.build(result);
    }

    /**
     * 查询显示器检测列表
     */
    @Override
    public List<DisplayTestVo> queryList(DisplayTestBo bo) {
        LambdaQueryWrapper<DisplayTest> lqw = buildQueryWrapper(bo);
        List<DisplayTestVo> displayTestVos = baseMapper.selectVoList(lqw);
        Set<String> deviceIds = displayTestVos.stream().map(DisplayTestVo::getId).collect(Collectors.toSet());

        LambdaQueryWrapper<DeviceFaultMap> deviceFaultMapLambdaQueryWrapper = Wrappers.lambdaQuery(DeviceFaultMap.class);
        deviceFaultMapLambdaQueryWrapper.in(DeviceFaultMap::getDeviceId, deviceIds);
        List<DeviceFaultMap> deviceFaultMapVos = deviceFaultMapMapper.selectList(deviceFaultMapLambdaQueryWrapper);
        Map<String, List<String>> stringListMap = deviceFaultMapVos.stream().collect(Collectors.groupingBy(DeviceFaultMap::getDeviceId, Collectors.mapping(DeviceFaultMap::getFaultName, Collectors.toList())));
        if (CollectionUtils.isNotEmpty(stringListMap)) {
            displayTestVos.forEach(d -> {
                d.setDeviceFaultMaps(stringListMap.get(d.getId()));
            });
        }
        return displayTestVos;
    }

    private LambdaQueryWrapper<DisplayTest> buildQueryWrapper(DisplayTestBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<DisplayTest> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getSn()), DisplayTest::getSn, bo.getSn());
        lqw.eq(StringUtils.isNotBlank(bo.getPoId()), DisplayTest::getPoId, bo.getPoId());
        return lqw;
    }

    /**
     * 新增显示器检测
     */
    @Override
    public Boolean insertByBo(DisplayTestBo bo) {

        //先判断是不是读取过
        DisplayTestBo displayTest = new DisplayTestBo();
        displayTest.setSn(bo.getSn().trim());
        List<DisplayTestVo> displayTestVos = this.queryList(displayTest);
        if (CollectionUtils.isNotEmpty(displayTestVos)) {
            //说明数据库中存在当前设备，或者SN读取错误
            throw new RuntimeException("读取失败，当前设备已存在，或者SN错误，请检查");
        }


        DisplayTest add = BeanUtil.toBean(bo, DisplayTest.class);

        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改显示器检测
     */
    @Override
    public Boolean updateByBo(DisplayTestBo bo) {
        DisplayTest update = BeanUtil.toBean(bo, DisplayTest.class);
        List<String> deviceFaultMaps = bo.getDeviceFaultMaps();
        List<DeviceFaultMap> deviceFaultMapList = deviceFaultMaps.stream().map(d -> {
            DeviceFaultMap deviceFaultMap = new DeviceFaultMap();
            deviceFaultMap.setFaultName(d);
            deviceFaultMap.setDeviceId(bo.getId());
            return deviceFaultMap;
        }).collect(Collectors.toList());

        validEntityBeforeSave(update);
        if(baseMapper.updateById(update) > 0){
            Map<String, Object> stringStringMap = new HashMap<>();
            stringStringMap.put("device_id",bo.getId());
            deviceFaultMapMapper.deleteByMap(stringStringMap);
            if (CollectionUtils.isNotEmpty(deviceFaultMapList)) {
                return deviceFaultMapMapper.insertBatch(deviceFaultMapList);
            }
            return true;
        }
        return false;

    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DisplayTest entity) {
        //TODO 做一些数据校验,如唯一约束
        entity.setBrand(entity.getBrand().trim());
        entity.setOriginBrand(entity.getOriginBrand().trim());
        entity.setModel(entity.getModel().trim());
        entity.setResolution(entity.getResolution().trim());
        entity.setSize(entity.getSize().trim());
        entity.setSn(entity.getSn().trim());
        entity.setPoId(entity.getPoId().trim());
        if (entity.getBrand().equals(entity.getOriginBrand())) {
            throw new RuntimeException("请修改正确的品牌后再点击确认");
        } else {
            //先判断字典里面有没有这个映射
            //获取品牌映射字典
            SysDictData sysDictData = new SysDictData();
            sysDictData.setDictType("test_display_brand_map");
            Map<String, String> brandMap = iSysDictDataService.selectDictDataList(sysDictData)
                .stream()
                .filter(d -> d.getStatus().equals("0"))
                .collect(Collectors.toMap(SysDictData::getDictLabel, SysDictData::getDictValue));
            String brand = brandMap.get(entity.getOriginBrand());
            if (StringUtils.isBlank(brand)) {
                sysDictData.setDictLabel(entity.getOriginBrand());
                sysDictData.setDictValue(entity.getBrand());
                sysDictData.setStatus("0");
                iSysDictDataService.insertDictData(sysDictData);
            }
        }
    }

    /**
     * 批量删除显示器检测
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }
}
